package haoji_juc.xujiahuanxing;

import javax.lang.model.SourceVersion;

/**
 * @program: Dome
 * @description:
 * @className: Dome
 * @author: rjt99999
 * @version: 1.0.0
 * @create: 2020-08-03 22:04
 **/

public class Dome {

/*
/*
 * 一、用于解决多线程安全问题的方式：
 *
 * synchronized:隐式锁
 * 1. 同步代码块
 *
 * 2. 同步方法
 *
 * jdk 1.5 后：
 * 3. 同步锁 Lock
 * 注意：是一个显示锁，需要通过 lock() 方法上锁，必须通过 unlock() 方法进行释放锁(一般放于fnilly)
 *
 *
 * wailt（） 放于 while ()中 使用--防止虚假唤醒
 */

    public static void main(String[] args) {

        Clerk clerk = new Clerk();

        Consumer consumer = new Consumer(clerk);
        Productor productor = new Productor(clerk);


        new Thread(consumer, "消费者").start();
        new Thread(productor, "生产者").start();


    }


}

//店员
class Clerk {


    //货物
    private int product = 0;


    //进货
    public synchronized void getProduct() {


        while (product >= 1) {


            System.out.println("产品已满");


            try {
                //生产者等待
                this.wait();//为了避免虚假唤醒问题，应该总是使用在循环中

            } catch (InterruptedException e) {
                e.printStackTrace();
            }




        }
        //如果不满

        System.out.println(Thread.currentThread().getName() + ":" + ++product);

        // 唤醒 生产线程（由消费者唤醒）
        this.notifyAll();


    }

    //卖货
    public synchronized void sale() {


        //如果缺货 则消费者等待
        while (product <= 0) {

            System.out.println("产品缺货");


            try {
                //则消费者等待
                this.wait();

            } catch (InterruptedException e) {
                e.printStackTrace();
            }


        }


        //不缺就消费
        System.out.println(Thread.currentThread().getName() + ":" + --product);

        //唤醒 消费线程
        this.notifyAll();

    }


}
//生产者

class Productor implements Runnable {

    private Clerk clerk;

    public Productor(Clerk clerk) {
        this.clerk = clerk;
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            //生产20个
            clerk.getProduct();

        }


    }
}

//消费者
class Consumer implements Runnable {

    private Clerk clerk;

    public Consumer(Clerk clerk) {

        this.clerk = clerk;
    }

    @Override
    public void run() {

        for (int i = 0; i < 20; i++) {

            clerk.sale();

        }

    }
}
